package com.yuan.support;

import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaScannerConnection;
import android.util.Log;
import android.webkit.MimeTypeMap;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;

public class FileUtils {
    private static final String TAG = FileUtils.class.getSimpleName();


    public static void testBitmap(final String filePath) {
        new Thread(new Runnable() {
            @Override
            public void run() {

                Log.d(TAG, "testBitmap: **********************填充前***********");
                System.gc();
                printMemory();

                ArrayList<Bitmap> list = new ArrayList<>();
                for (int i = 0; i < 50; i++) {
                    Bitmap bitmap = BitmapFactory.decodeFile(filePath);
                    list.add(bitmap);
                    // Log.d(TAG, "" + i + " = " + bitmap);
                }

                Log.d(TAG, "testBitmap: **********************填充后***********");
                System.gc();
                printMemory();

                Log.d(TAG, "testBitmap: **********************填充后置null***********");
                for (int i = 0; i < 50; i++) {
                    Bitmap bitmap = list.get(i); // 不新建对象，只是新建引用
                    // Log.d(TAG, "" + i + " = " + bitmap);
                    bitmap.recycle(); // 缺少会闪退
                    // bitmap = null;
                    // list.set(i, null); // 与 bitmap = null;等价
                }
                System.gc();
                printMemory();

                Log.d(TAG, "testBitmap: **********************释放list***********");
                System.gc();
                list.clear();
                printMemory();
                // 只释放list与填充后没变化
            }
        }).start();
    }

    /**
     * memoryClass与maxMemory只是单位不同
     * 只能统计Java层，未统计Native层
     */
    public static void printMemory() {
        Context context = ContextUtils.getContextByReflection();
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        if (am != null) {
            int memoryClass = am.getMemoryClass();
            Log.d(TAG, "printMemory: am.getMemoryClass=" + getFileSize(memoryClass)); // M
        }
        long maxMemory = Runtime.getRuntime().maxMemory(); // B
        long totalMemory = Runtime.getRuntime().totalMemory();
        long freeMemory = Runtime.getRuntime().freeMemory();
        Log.d(TAG, "printMemory: maxMemory=" + getFileSize(maxMemory));
        Log.d(TAG, "printMemory: totalMemory=" + getFileSize(totalMemory));
        Log.d(TAG, "printMemory: freeMemory=" + getFileSize(freeMemory));
    }

    /**
     * 将字节数转化为MB、KB等，保留一位小数
     */
    public static String getFileSize(long size) {
        StringBuffer stringBuffer = new StringBuffer();
        DecimalFormat decimalFormat = new DecimalFormat("###.0");
        try {
            if (size >= 1024 * 1024) {
                stringBuffer.append(decimalFormat.format(size / (1024.0 * 1024.0))).append("MB");
            } else if (size >= 1024) {
                stringBuffer.append(decimalFormat.format(size / (1024.0))).append("KB");
            } else if (size >= 0) {
                stringBuffer.append(size).append("B");
            } else {
                stringBuffer.append("0B");
            }
        } catch (Exception e) {
            Log.e(TAG, "getFileSize: " + e.getMessage());
            e.printStackTrace();
        }
        return stringBuffer.toString();
    }


    /**
     * 通过图片路径对图片进行压缩
     *
     * @param filePath    图片文件的路径，默认为JPG格式
     * @param maxFileSize 压缩后图片文件不超过的磁盘大小，单位KB
     */
    public static void compressPic(String filePath, int maxFileSize) throws Exception {
        // 图片路径转Bitmap
        Bitmap bitmap = BitmapFactory.decodeFile(filePath); // 可读即可解码

        int quality = 100;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        // 字节转化为KB，若超过目标值，且还可以继续压缩则继续压缩，否则即便超过最大值也不再压缩
        while (baos.toByteArray().length / 1024 > maxFileSize) {
            quality -= 5;  // 压缩质量递减步进
            if (quality < 0) {
                break; // 压缩质量只能介于0~100，否则参数异常
            }
            Log.d(TAG, "compressPic: quality=" + quality);
            baos.reset();
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
        }

        bitmap.recycle(); // todo

        String extensionWithDot = getExtensionWithDot(filePath); // 获取带.的后缀
        String backupFilePath = filePath.replace(extensionWithDot, "_backup" + extensionWithDot);

        File file = new File(filePath);
        File backupFile = new File(backupFilePath); // 备份文件

        // 把源文件重命名为备份文件，将压缩文件输出到原文件路径

        boolean renameSuccess = file.renameTo(backupFile);
        Log.d(TAG, "compressPic: renameSuccess=" + renameSuccess);

        FileOutputStream fos = new FileOutputStream(filePath);
        fos.write(baos.toByteArray());
        fos.flush();
        fos.close();

        backupFile.delete();

        scanFile(filePath, null);
        scanFile(backupFilePath, null);
    }


    /**
     * 通知该媒体库扫描该文件路径，便于及时更新其他应用，如图库
     */
    public static void scanFile(String filePath, MediaScannerConnection.OnScanCompletedListener callback) {
        MediaScannerConnection.scanFile(ContextUtils.getContextByReflection(),
                new String[]{filePath},
                new String[]{getMimeTypeFromExtension(filePath)},
                callback);
    }

    /**
     * 通过文件路径的后缀获取其MimeType
     */
    public static String getMimeTypeFromExtension(String filePath) {
        String extension = getExtension(filePath);
        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
        return mimeType;
    }

    /**
     * 通过文件路径获取不带.的后缀
     */
    public static String getExtension(String filePath) {
        int lastDot = filePath.lastIndexOf(".");
        String extension = filePath.substring(lastDot + 1); // 不带.的后缀
        return extension;
    }

    /**
     * 通过文件路径获取带.的后缀
     */
    public static String getExtensionWithDot(String filePath) {
        int lastDot = filePath.lastIndexOf(".");
        String extension = filePath.substring(lastDot); // 带.的后缀
        return extension;
    }
}
